home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / sync / syncSysV.c < prev    next >
C/C++ Source or Header  |  1990-10-05  |  17KB  |  715 lines

  1. /* 
  2.  * syncSysV.c --
  3.  *
  4.  *    Do system V compatibility synchronization functions:
  5.  *        semctl, semget, semop
  6.  *
  7.  * Copyright (C) 1990 Regents of the University of California
  8.  * All rights reserved.
  9.  */
  10.  
  11. #ifndef lint
  12. static char rcsid[] = "$Header: /sprite/src/kernel/sync/RCS/syncSysV.c,v 1.5 90/10/05 17:50:36 mendel Exp $ SPRITE (Berkeley)";
  13. #endif /* not lint */
  14.  
  15. #include <sprite.h>
  16. #include <sync.h>
  17. #include <spriteTime.h>
  18. #include <fs.h>
  19. #include <stdio.h>
  20. #include <bstring.h>
  21. #include <vm.h>
  22. #include <stdlib.h>
  23.  
  24.  
  25. Sync_SysVSem semTable[SEMMNI];
  26. static int totalSems = 0;
  27.  
  28. static Sync_Lock semLock = Sync_LockInitStatic("Sync:sysVSemaphores");
  29. #define LOCKPTR (&semLock)
  30.  
  31. /*
  32.  * Debugging print statement declaration.
  33.  */
  34. #define dprintf if (vmShmDebug) printf
  35. extern int vmShmDebug;
  36.  
  37. /*
  38.  * Compat. defs.
  39.  */
  40. #define EPERM    GEN_EPERM
  41. #define ENOENT    GEN_ENOENT
  42. #define EINTR    GEN_EINTR
  43. #define EACCES    GEN_EACCES
  44. #define EEXIST    GEN_EEXIST
  45. #define EINVAL    GEN_EINVAL
  46. #define ENOSPC    GEN_ENOSPC
  47.  
  48. #define EFBIG    GEN_EFBIG
  49. #define    E2BIG    GEN_E2BIG
  50. #define EAGAIN    GEN_EAGAIN
  51. #define EFAULT    GEN_EFAULT
  52. #define ERANGE    GEN_ERANGE
  53. #define EIDRM    GEN_EIDRM
  54.  
  55. #define DEFAULTGID 115
  56.  
  57. static int semInit = 0;
  58.  
  59. /*
  60.  *----------------------------------------------------------------------
  61.  *
  62.  * Sync_SemInit --
  63.  *
  64.  *    Perform semaphore initialization functions.
  65.  *
  66.  * Results:
  67.  *    None.
  68.  *
  69.  * Side effects:
  70.  *    Initializes datastructures.
  71.  *
  72.  *----------------------------------------------------------------------
  73.  */
  74. void
  75. Sync_SemInit()
  76. {
  77.     int i;
  78.     if (semInit == 1234) {
  79.     return;
  80.     }
  81.     semInit = 1234;
  82.     LOCK_MONITOR;
  83.     for (i=0;i<SEMMNI;i++) {
  84.     semTable[i].sem_base = (struct sem *)NIL;
  85.     }
  86.     UNLOCK_MONITOR;
  87. }
  88.  
  89. /*
  90.  *----------------------------------------------------------------------
  91.  *
  92.  * Sync_SemctlStub --
  93.  *
  94.  *    Perform control functions on semaphores.
  95.  *
  96.  * Results:
  97.  *    Returns result of the function.
  98.  *
  99.  * Side effects:
  100.  *    Performs a function on the semaphore.
  101.  *
  102.  *----------------------------------------------------------------------
  103.  */
  104. ReturnStatus
  105. Sync_SemctlStub(semid, semnum, cmd, arg, retValOut)
  106.     int        semid;        /* Semaphore group identifier. */
  107.     int        semnum;        /* Semaphore number. */
  108.     int        cmd;        /* Command to perform. */
  109.     union semun    arg;        /* Command argument. */
  110.     int        *retValOut;    /* Result of command. */
  111. {
  112.  
  113.     ReturnStatus    status;
  114.     int            perm;
  115.     Sync_SysVSem    *semPtr;
  116.     int            uid;
  117.     struct semid_ds    semBuf;
  118.     int            i;
  119.     int            nsems;
  120.     struct sem        *curSem;
  121.     ushort        array[SEMMSL];
  122.     Time        timeVal;
  123.     int            retVal=0;
  124.  
  125.     dprintf("call: semctl(%d, %d, %d, %x)\n", semid, semnum, cmd, arg);
  126.     Sync_SemInit();
  127.     LOCK_MONITOR;
  128.     if (cmd != GETKEYS) {
  129.     status = Sync_SemStruct(semid, &perm, &semPtr);
  130.     if (status != SUCCESS) {
  131.         UNLOCK_MONITOR;
  132.         return status;
  133.     }
  134.     }
  135.     switch (cmd) {
  136.  
  137.     case SETVAL:
  138.     case SETALL:
  139.         if (!(perm & SEM_A)) {
  140.         UNLOCK_MONITOR;
  141.         dprintf("Access denied\n");
  142.         return EACCES;
  143.         }
  144.         break;
  145.     case IPC_SET:
  146.     case IPC_RMID:
  147.         uid=Proc_GetEffectiveProc()->effectiveUserID;
  148.         if (uid != 0 && uid != semPtr->sem_perm.uid &&
  149.             uid != semPtr->sem_perm.cuid) {
  150.         UNLOCK_MONITOR;
  151.         dprintf("Permission denied\n");
  152.         return EPERM;
  153.         }
  154.         break;
  155.     case GETKEYS:
  156.         break;
  157.     case GETVAL:
  158.     case GETPID:
  159.     case GETNCNT:
  160.     case GETZCNT:
  161.     case GETALL:
  162.     case IPC_STAT:
  163.         if (!(perm & SEM_R)) {
  164.         UNLOCK_MONITOR;
  165.         dprintf("Access denied\n");
  166.         return EACCES;
  167.         }
  168.         break;
  169.     default:
  170.         UNLOCK_MONITOR;
  171.         dprintf("invalid command\n");
  172.         return EINVAL;
  173.     }
  174.         
  175.     if (cmd == GETVAL || cmd == SETVAL || cmd == GETPID || cmd == GETNCNT ||
  176.         cmd == GETZCNT) {
  177.     if (semnum < 0 || semnum >= semPtr->sem_nsems) {
  178.         UNLOCK_MONITOR;
  179.         dprintf("Invalid semnum: %d\n",semnum);
  180.         return EINVAL;
  181.     }
  182.     curSem = &semPtr->sem_base[semnum];
  183.     }
  184.     switch (cmd) {
  185.     case GETVAL:
  186.         retVal = curSem->semval;
  187.         dprintf("semctl(GETVAL) returns %d\n", retVal);
  188.         break;
  189.     case SETVAL:
  190.         if (arg.val < 0 || arg.val > SEMVMX) {
  191.         UNLOCK_MONITOR;
  192.         dprintf("Invalid value %d\n",arg.val);
  193.         return ERANGE;
  194.         }
  195.         curSem->semval = arg.val;
  196.         if ( (arg.val == 0 && curSem->semzcnt > 0) ||
  197.             (arg.val > 0 && curSem->semncnt > 0)) {
  198.         Sync_Broadcast(&curSem->semLock);
  199.         }
  200.         dprintf("semctl(SETVAL) returns %d\n", retVal);
  201.         break;
  202.     case GETPID:
  203.         retVal = curSem->sempid;
  204.         dprintf("semctl(GETPID) returns %d\n", retVal);
  205.         break;
  206.     case GETNCNT:
  207.         retVal = curSem->semncnt;
  208.         dprintf("semctl(GETNCNT) returns %d\n", retVal);
  209.         break;
  210.     case GETZCNT:
  211.         retVal = curSem->semzcnt;
  212.         dprintf("semctl(GETZCNT) returns %d\n", retVal);
  213.         break;
  214.     case GETALL:
  215.         for (i=0;i<semPtr->sem_nsems;i++) {
  216.         array[i] = semPtr->sem_base[i].semval;
  217.         }
  218.         status = Vm_CopyOut(sizeof(ushort)*semPtr->sem_nsems,
  219.             (Address) array, (Address) arg.array);
  220.         if (status != SUCCESS) {
  221.         UNLOCK_MONITOR;
  222.         dprintf("Copy-out fault\n");
  223.         return EFAULT;
  224.         }
  225.         dprintf("semctl(GETALL) done\n");
  226.         break;
  227.     case GETKEYS:
  228.         bzero((Address)&semBuf, sizeof(struct semid_ds));
  229.         for (i=0;i<SEMMNI;i++) {
  230.         semBuf.sem_perm.mode = semTable[i].sem_perm.mode;
  231.         semBuf.sem_perm.key = semTable[i].sem_perm.key;
  232.         semBuf.sem_perm.seq = semTable[i].sem_perm.seq;
  233.         semBuf.sem_perm.uid = semTable[i].sem_perm.uid;
  234.         semBuf.sem_perm.gid = semTable[i].sem_perm.gid;
  235.         semBuf.sem_nsems =
  236.             (semTable[i].sem_base == (struct sem *)NIL) ? 0 : 1;
  237.         status = Vm_CopyOut(sizeof(struct semid_ds), (Address) &semBuf,
  238.             (Address) (arg.buf+i));
  239.         if (status != SUCCESS) {
  240.             UNLOCK_MONITOR;
  241.             dprintf("Copy-out fault\n");
  242.             return EFAULT;
  243.         }
  244.         }
  245.         dprintf("semctl(GETALL) done\n");
  246.         break;
  247.     case IPC_STAT:
  248.         status = Vm_CopyOut(sizeof(struct semid_ds), (Address) semPtr,
  249.             (Address) arg.buf);
  250.         if (status != SUCCESS) {
  251.         UNLOCK_MONITOR;
  252.         dprintf("Copy-out fault\n");
  253.         return EFAULT;
  254.         }
  255.         dprintf("semctl(IPC_STAT) done\n");
  256.         break;
  257.     case SETALL:
  258.         status = Vm_CopyIn(sizeof(ushort)*semPtr->sem_nsems,
  259.             (Address) arg.array, (Address) array);
  260.         if (status != SUCCESS) {
  261.         UNLOCK_MONITOR;
  262.         dprintf("Copy-in fault\n");
  263.         return EFAULT;
  264.         }
  265.  
  266.         for (i=0;i<semPtr->sem_nsems;i++) {
  267.         if (array[i] < 0 || array[i] > SEMVMX) {
  268.             UNLOCK_MONITOR;
  269.             dprintf("Invalid value: %d\n",array[i]);
  270.             return ERANGE;
  271.         }
  272.         }
  273.         for (i=0;i<semPtr->sem_nsems;i++) {
  274.         semPtr->sem_base[i].semval = array[i];
  275.         }
  276.         for (i=0;i<semPtr->sem_nsems;i++) {
  277.         curSem = &semPtr->sem_base[i];
  278.         if ( (array[i] == 0 && curSem->semzcnt > 0) ||
  279.             (array[i] > 0 && curSem->semncnt > 0)) {
  280.             Sync_Broadcast(&curSem->semLock);
  281.         }
  282.         }
  283.         dprintf("semctl(SETALL) done\n");
  284.         break;
  285.     case IPC_SET:
  286.         status = Vm_CopyIn(sizeof(struct semid_ds), (Address) arg.buf,
  287.             (Address) &semBuf);
  288.         if (status != SUCCESS) {
  289.         UNLOCK_MONITOR;
  290.         dprintf("Copy-in fault\n");
  291.         return EFAULT;
  292.         }
  293.         semPtr->sem_perm.uid = semBuf.sem_perm.uid;
  294.         semPtr->sem_perm.gid = semBuf.sem_perm.gid;
  295.         semPtr->sem_perm.mode = semBuf.sem_perm.mode & 0666;
  296.         dprintf("semctl(IPC_SET) done\n");
  297.         break;
  298.     case IPC_RMID:
  299.         semPtr->sem_perm.seq++;
  300.         nsems = semPtr->sem_nsems;
  301.         if (nsems > SEMMNI) nsems = SEMMNI;
  302.         curSem = semPtr->sem_base;
  303.         semPtr->sem_base = (struct sem *)NIL;
  304.         semPtr->sem_perm.key = 0;
  305.         for (i=0;i<nsems;i++) {
  306.         if (curSem[i].semzcnt != 0 || curSem[i].semncnt != 0) {
  307.             Sync_Broadcast(&curSem->semLock);
  308.         }
  309.         }
  310.         free((char *)curSem);
  311.         dprintf("semctl(IPC_RMID) done\n");
  312.         break;
  313.     }
  314.     if (cmd == SETVAL || cmd == SETALL || cmd == IPC_SET) {
  315.     Timer_GetRealTimeOfDay(&timeVal, (int *)NIL, (Boolean *)NIL);
  316.     semPtr->sem_ctime = timeVal.seconds;
  317.     }
  318.     UNLOCK_MONITOR;
  319.     status = Vm_CopyOut(sizeof(int), (Address) &retVal, (Address) retValOut);
  320.     if (status != SUCCESS) {
  321.     dprintf("Copy-out fault\n");
  322.     return EFAULT;
  323.     }
  324.     return SUCCESS;
  325. }
  326.  
  327. /*
  328.  *----------------------------------------------------------------------
  329.  *
  330.  * Sync_SemgetStub --
  331.  *
  332.  *    Gets a set of semaphores.
  333.  *
  334.  * Results:
  335.  *    Returns result of the function.
  336.  *
  337.  * Side effects:
  338.  *    May create semaphore datastructures.
  339.  *
  340.  *----------------------------------------------------------------------
  341.  */
  342. ReturnStatus
  343. Sync_SemgetStub(key, nsems, semflg, retValOut)
  344.     long    key;        /* Semaphore key. */
  345.     int        nsems;        /* Number of semaphores requested. */
  346.     int        semflg;        /* Creation flag. */
  347.     int        *retValOut;    /* Result of operation. */
  348.     
  349. {
  350.     int            i;
  351.     Sync_SysVSem    *semPtr;
  352.     Proc_ControlBlock    *procPtr;
  353.     int            uid;
  354.     Time        timeVal;
  355.     int            retVal;
  356.     ReturnStatus    status;
  357.     Fs_ProcessState    *fsPtr;
  358.  
  359.     dprintf("call: semget(%d, %d, %d)\n", key, nsems, semflg);
  360.     Sync_SemInit();
  361.     if (nsems < 0 || nsems > SEMMSL) {
  362.     UNLOCK_MONITOR;
  363.     dprintf("Invalid number of semaphores: %d\n",nsems);
  364.     return EINVAL;
  365.     }
  366.     LOCK_MONITOR;
  367.     if (key != IPC_PRIVATE) {
  368.     /*
  369.      * Check if the key is in the semaphore table.
  370.      */
  371.     semPtr = NULL;
  372.     for (i=0;i<SEMMNI;i++) {
  373.         if ((long)semTable[i].sem_perm.key == key &&
  374.             semTable[i].sem_base != (struct sem *)NIL) {
  375.         semPtr = &semTable[i];
  376.         break;
  377.         }
  378.     }
  379.     if (semPtr == NULL && !(semflg & IPC_CREAT)) {
  380.         UNLOCK_MONITOR;
  381.         dprintf("No semaphore %d\n",key);
  382.         return ENOENT;
  383.     }
  384.     }
  385.     if (key == IPC_PRIVATE || semPtr == NULL) {
  386.     /*
  387.      * Want to create a new semaphore set.
  388.      */
  389.     if (nsems == 0) {
  390.         UNLOCK_MONITOR;
  391.         dprintf("Can't create 0 semaphores.\n");
  392.         return EINVAL;
  393.     }
  394.     semPtr = NULL;
  395.     for (i=0;i<SEMMNI;i++) {
  396.         if (semTable[i].sem_base == (struct sem *)NIL) {
  397.         semPtr = &semTable[i];
  398.         break;
  399.         }
  400.     }
  401.     if (semPtr == NULL) {
  402.         UNLOCK_MONITOR;
  403.         dprintf("Semaphore table full\n");
  404.         return ENOSPC;
  405.     }
  406.     if (totalSems+nsems > SEMMNS) {
  407.         UNLOCK_MONITOR;
  408.         dprintf("Semaphore table full\n");
  409.         return ENOSPC;
  410.     }
  411.     procPtr=Proc_GetEffectiveProc();
  412.     uid = procPtr->effectiveUserID;
  413.     semPtr->sem_perm.uid = procPtr->effectiveUserID;
  414.     semPtr->sem_perm.cuid = procPtr->effectiveUserID;
  415.     fsPtr = procPtr->fsPtr;
  416.     if (fsPtr->numGroupIDs > 0) {
  417.         semPtr->sem_perm.gid = fsPtr->groupIDs[0];
  418.     } else {
  419.         semPtr->sem_perm.gid = DEFAULTGID;
  420.     }
  421.     semPtr->sem_perm.cgid = semPtr->sem_perm.gid;
  422.     semPtr->sem_perm.mode = semflg&0666;
  423.     semPtr->sem_perm.key = key;
  424.     semPtr->sem_base = (struct sem *)malloc(sizeof(struct sem)*nsems);
  425.     Timer_GetRealTimeOfDay(&timeVal, (int *) NIL, (Boolean *) NIL);
  426.     semPtr->sem_nsems = nsems;
  427.     semPtr->sem_otime = 0;
  428.     semPtr->sem_ctime = timeVal.seconds;
  429.     for (i=0;i<nsems;i++) {
  430.         semPtr->sem_base[i].semval = 0;
  431.         semPtr->sem_base[i].sempid = 0;
  432.         semPtr->sem_base[i].semncnt = 0;
  433.         semPtr->sem_base[i].semzcnt = 0;
  434.     }
  435.     } else {
  436.     if (semPtr->sem_nsems < nsems) {
  437.         UNLOCK_MONITOR;
  438.         dprintf("Semaphore exists, but not enough semaphores.\n");
  439.         return EINVAL;
  440.     }
  441.     if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
  442.         UNLOCK_MONITOR;
  443.         dprintf("Semaphore set already exists\n");
  444.         return EEXIST;
  445.     }
  446.     if (((semflg & 0333) & semPtr->sem_perm.mode) != (semflg & 0333)) {
  447.         UNLOCK_MONITOR;
  448.         dprintf("Permission denied: mode %o\n",semPtr->sem_perm.mode);
  449.         return EACCES;
  450.     }
  451.     }
  452.     retVal = semPtr->sem_perm.seq*SEMMNI+(semPtr-semTable);
  453.     UNLOCK_MONITOR;
  454.     status = Vm_CopyOut(sizeof(int), (Address) &retVal, (Address) retValOut);
  455.     if (status != SUCCESS) {
  456.     dprintf("Copy-out failure\n");
  457.     return EFAULT;
  458.     }
  459.     dprintf("semget: returns %d\n",retVal);
  460.     return SUCCESS;
  461. }
  462.  
  463. /*
  464.  *----------------------------------------------------------------------
  465.  *
  466.  * Sync_SemopStub --
  467.  *
  468.  *    Perform semaphore operations on semaphores.
  469.  *
  470.  * Results:
  471.  *    Returns result of the function.
  472.  *
  473.  * Side effects:
  474.  *    Performs a function on the semaphore.
  475.  *
  476.  *----------------------------------------------------------------------
  477.  */
  478. ReturnStatus
  479. Sync_SemopStub(semid, sopsIn, nsops, retValOut)
  480.     int            semid;        /* Semaphore group identifier. */
  481.     struct sembuf    *sopsIn;    /* Operations to perform. */
  482.     int            nsops;        /* Number of operations. */
  483.     int            retValOut;    /* Result of operation. */
  484.     
  485. {
  486.     int            perms;
  487.     Sync_SysVSem    *semPtr;
  488.     ReturnStatus    status;
  489.     int            i,j;
  490.     struct sembuf    sops[SEMOPM];
  491.     int            seq;
  492.     int            semmod[SEMMSL];
  493.     Time        timeVal;
  494.     int            pid = Proc_GetEffectiveProc()->processID;
  495.     struct sem        *curSem;
  496.     int            retVal;
  497.     Boolean        sig;
  498.  
  499.     dprintf("call: semop(%d, %x, %d)\n", semid, sopsIn, nsops);
  500.  
  501.     if (nsops <= 0 || nsops > SEMOPM) {
  502.     dprintf("Too many semaphore operations\n");
  503.     return E2BIG;
  504.     }
  505.  
  506.     Sync_SemInit();
  507.  
  508.     status = Vm_CopyIn(sizeof(struct sembuf)*nsops, (Address) sopsIn,
  509.         (Address) sops);
  510.     if (status != SUCCESS) {
  511.     dprintf("Copy-in fault\n");
  512.     return EFAULT;
  513.     }
  514.     LOCK_MONITOR;
  515.     status = Sync_SemStruct(semid, &perms, &semPtr);
  516.     if (status != SUCCESS) {
  517.     UNLOCK_MONITOR;
  518.     return status;
  519.     }
  520.     for (i=0;i<nsops;i++) {
  521.     if (sops[i].sem_num < 0 || sops[i].sem_num >= semPtr->sem_nsems) {
  522.         UNLOCK_MONITOR;
  523.         dprintf("Semaphore value too big: #%d = %d, max: %d\n",
  524.             i, sops[i].sem_num, semPtr->sem_nsems);
  525.         return EFBIG;
  526.     }
  527.     if ((sops[i].sem_op != 0 && !(perms & SEM_A)) ||
  528.         (sops[i].sem_op == 0 && !(perms & SEM_R))) {
  529.         UNLOCK_MONITOR;
  530.         dprintf("Semaphore access denied\n");
  531.         return EACCES;
  532.     }
  533.     if (sops[i].sem_flg & SEM_UNDO) {
  534.         printf("semop: SEM_UNDO not implemented\n");
  535.         UNLOCK_MONITOR;
  536.         return EINVAL;
  537.     }
  538.     }
  539.  
  540. retry:
  541.  
  542.     status = SUCCESS;
  543.     for (i=0;i<nsops;i++) {
  544.     int sem_op = sops[i].sem_op;
  545.     curSem = &semPtr->sem_base[sops[i].sem_num];
  546.     retVal = curSem->semval;
  547.     if (sem_op < 0) {
  548.         if (curSem->semval >= -sem_op) {
  549.         curSem->semval -= -sem_op;
  550.         } else {
  551.         break;
  552.         }
  553.     } else if (sops[i].sem_op > 0) {
  554.         if (curSem->semval + sem_op > SEMVMX) {
  555.         status = ERANGE;
  556.         break;
  557.         }
  558.         curSem->semval += sem_op;
  559.     } else {
  560.         if (curSem->semval != 0) {
  561.         break;
  562.         }
  563.     }
  564.     }
  565.  
  566.     if (i==nsops) {
  567.     /*
  568.      * Success.
  569.      */
  570.     for (i=0;i<semPtr->sem_nsems;i++) {
  571.         semmod[i] = 0;
  572.     }
  573.     for (i=0;i<nsops;i++) {
  574.         if (sops[i].sem_num != 0) {
  575.         semmod[sops[i].sem_num]++;
  576.         }
  577.     }
  578.     Timer_GetRealTimeOfDay(&timeVal, (int *)NIL, (Boolean *) NIL);
  579.     semPtr->sem_otime = timeVal.seconds;
  580.     for (i=0;i<semPtr->sem_nsems;i++) {
  581.         if (semmod[i] != 0) {
  582.         curSem = &semPtr->sem_base[i];
  583.         curSem->sempid = pid;
  584.         if ((curSem->semzcnt != 0 && curSem->semval == 0) ||
  585.             (curSem->semncnt != 0 && curSem->semval != 0)) {
  586.             Sync_Broadcast(&curSem->semLock);
  587.         }
  588.         }
  589.     }
  590.     UNLOCK_MONITOR;
  591.     status = Vm_CopyOut(sizeof(int), (Address) &retVal,
  592.         (Address) retValOut);
  593.     if (status != SUCCESS) {
  594.         dprintf("Copy-out fault\n");
  595.         return EFAULT;
  596.     }
  597.     return SUCCESS;
  598.     } else {
  599.     /*
  600.      * Failure;
  601.      */
  602.     /*
  603.      * Undo any changes.
  604.      */
  605.     for (j=0;j<i;j++) {
  606.         semPtr->sem_base[sops[j].sem_num].semval -= sops[j].sem_op;
  607.     }
  608.     if (status != SUCCESS) {
  609.         UNLOCK_MONITOR;
  610.         return status;
  611.     }
  612.     /*
  613.      * Wait if necessary.  Then try again.
  614.      */
  615.     if (!(sops[i].sem_flg & IPC_NOWAIT)) {
  616.         if (sops[i].sem_op == 0) {
  617.         curSem->semzcnt++;
  618.         } else {
  619.         curSem->semncnt++;
  620.         }
  621.         seq = semPtr->sem_perm.seq;
  622.         sig = Sync_Wait(&curSem->semLock, TRUE);
  623.         if (seq != semPtr->sem_perm.seq) {
  624.         UNLOCK_MONITOR;
  625.         dprintf("Semaphore removed\n");
  626.         return EIDRM;
  627.         }
  628.         if (sops[i].sem_op == 0) {
  629.         curSem->semzcnt--;
  630.         } else {
  631.         curSem->semncnt--;
  632.         }
  633.         if (sig) {
  634.         UNLOCK_MONITOR;
  635.         dprintf("Semaphore interrupted\n");
  636.         return EINTR;
  637.         } else {
  638.         goto retry;
  639.         }
  640.     } else {
  641.         UNLOCK_MONITOR;
  642.         dprintf("Semaphore would block\n");
  643.         return EAGAIN;
  644.     }
  645.     }
  646. }
  647.  
  648. /*
  649.  *----------------------------------------------------------------------
  650.  *
  651.  * Sync_SemStruct --
  652.  *
  653.  *    Get the semaphore structure, given the identifier.
  654.  *    This routine checks the associated permissions.
  655.  *
  656.  * Results:
  657.  *    Returns SUCCESS or error condition.
  658.  *
  659.  * Side effects:
  660.  *    None.
  661.  *
  662.  *----------------------------------------------------------------------
  663.  */
  664. ReturnStatus
  665. Sync_SemStruct(id, perm, retPtr)
  666.     int            id;        /* Semaphore id value. */
  667.     int            *perm;        /* (Return) permissions. */
  668.     Sync_SysVSem    **retPtr;    /* (Return) Semaphore structure. */
  669.  
  670. {
  671.     Sync_SysVSem    *semPtr;
  672.     Proc_ControlBlock    *procPtr;
  673.     int uid, gid;
  674.     int uperm;
  675.     Fs_ProcessState    *fsPtr;
  676.  
  677.     if (id < 0) return EINVAL;
  678.  
  679.     semPtr = &semTable[id%SEMMNI];
  680.     *retPtr = semPtr;
  681.     if (semPtr->sem_perm.seq != id/SEMMNI ||
  682.         semPtr->sem_base == (struct sem *) NIL ) {
  683.     /*
  684.      * No such semaphore.
  685.      */
  686.     dprintf("No semaphore %d\n",id);
  687.     return EINVAL;
  688.     }
  689.     /*
  690.      * Check permissions.
  691.      */
  692.     procPtr=Proc_GetEffectiveProc();
  693.     uid = procPtr->effectiveUserID;
  694.     fsPtr = procPtr->fsPtr;
  695.     if (fsPtr->numGroupIDs > 0) {
  696.     gid = fsPtr->groupIDs[0];
  697.     } else {
  698.     gid = DEFAULTGID;
  699.     printf("Warning: process has no gid\n");
  700.     }
  701.     if (uid == 0) {
  702.     *perm = SEM_A | SEM_R;
  703.     return SUCCESS;
  704.     }
  705.     if (uid == semPtr->sem_perm.uid || uid == semPtr->sem_perm.cuid) {
  706.     uperm = semPtr->sem_perm.mode;
  707.     } else if (gid == semPtr->sem_perm.gid || gid == semPtr->sem_perm.cgid) {
  708.     uperm = semPtr->sem_perm.mode<<3;
  709.     } else {
  710.     uperm = semPtr->sem_perm.mode<<6;
  711.     }
  712.     *perm = uperm & (SEM_A | SEM_R);
  713.     return SUCCESS;
  714. }
  715.